/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pr2.cruce;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import pr2.cromosoma.CromosomaPVC;

/**
 *
 * @author Gonzalo Ortiz Jaureguizar (gortiz at software.imdea.org)
 */
public class OXOrdenPrioritario extends EstrategiaCruce<CromosomaPVC> {
    /**
     * todas las posiciones posibles (de 0 a size-1) aleatoriamente mezcladas
     */
    private final ArrayList<Integer> posiciones;
    /**
     * set de posiciones seleccionadas
     */
    private final ArrayList<Integer> seleccionados;
    /**
     * Si padre1.get(seleccionados.get(i)) = k, padre2.get(posicionesOtroPadre.get(i)) = k
     */
    private final ArrayList<Integer> posicionesOtroPadre;

    public OXOrdenPrioritario(int size) {
        super(size);
        posiciones = new ArrayList<Integer>(size);
        for(int i = 0; i < size; i++) {
            posiciones.add(i);
        }
        seleccionados = new ArrayList<Integer>(size);
        posicionesOtroPadre = new ArrayList<Integer>(size);
    }

    private void elegir() {
        Collections.shuffle(posiciones);
        int maxSeleccionados = (int) (Math.random() * posiciones.size());
        
        seleccionados.clear();
        for(int i = 0; i < maxSeleccionados; i++) {
            seleccionados.add(posiciones.get(i));
        }
    }

    private void generarHijo(List<Integer> padreActual, List<Integer> otroPadre, List<Integer> hijoActual) {
        posicionesOtroPadre.clear();
        for(Integer i : seleccionados) {
            Integer ciudad = padreActual.get(i);
            posicionesOtroPadre.add(otroPadre.indexOf(ciudad));
        }
        int leidosDePadreActual = 0;
        for(int i = 0; i < hijoActual.size(); i++) {
            int ciudad;
            if(posicionesOtroPadre.contains(i)) { //copiamos el siguiente del padre actual
                ciudad = padreActual.get(seleccionados.get(leidosDePadreActual));
                leidosDePadreActual++;
            }
            else { //copiamos el iesimo del otro padre
                ciudad = otroPadre.get(i);
            }
            hijoActual.set(i, ciudad);
        }
    }

    @Override
    protected void cruzar(CromosomaPVC padre1, CromosomaPVC padre2, CromosomaPVC hijo1, CromosomaPVC hijo2) {
        elegir();

        if(seleccionados.size() == posiciones.size()) { //todos quedarian igual
            hijo1.copia(padre1);
            hijo2.copia(padre2);
            return ;
        }

        List<Integer> pg1 = padre1.getGenes();
        List<Integer> pg2 = padre2.getGenes();
        List<Integer> hg1 = hijo1.getGenes();
        List<Integer> hg2 = hijo2.getGenes();

        generarHijo(pg1, pg2, hg1);
        generarHijo(pg2, pg1, hg2);
    }

}
